<?

class mysqlFunctions{


	function recursivDeleteOldParity($Grp,$Prefixe)
	{
		for ($i=0;$i<count($Grp);$i++)
		{
			$SaveGrp=$Grp[$i]["Condition"]["Groupe"];
			unset($Grp[$i]["Condition"]["Groupe"]);
			foreach ($Grp[$i]["Condition"] as $K=>$C)
			{
				if (strstr($C,$Prefixe)){unset($Grp[$i]["Condition"][$K]);}
			}
			$SaveGrp = mysqlFunctions::recursivDeleteOldParity($SaveGrp,$Prefixe);
			if (count($Grp[$i]["Condition"])==0) unset($Grp[$i]);
			$Grp[$i]["Condition"]["Groupe"] = $SaveGrp;
		}
		return $Grp;
	}

	function joinRecursiv($Tab,$Data,$i) {
		//On ajoute une premiere table d index correspondant
		//$GLOBALS["Systeme"]->Log->log("DEBUG ".$this->isReflexive($Tab[$i]["Nom"]));
		switch ($this->isReflexive($Tab[$i]["Nom"])){
			case "1":
				if ($i>0){
					//Il faut retirer la contrainte de jointure de la paire precedente
					$Gout="";
					$Out=$Data;
					if (is_array($Data["Groupe"]))
					$Data["Groupe"] = mysqlFunctions::recursivDeleteOldParity($Data["Groupe"],mysqlFunctions::getPrefixe($Tab,$i).".");
					/*foreach ($Data["Groupe"] as $Kg=>$G){
						$Cout="";
						$SaveGrp = $G["Condition"]["Groupe"];
						unset($G["Condition"]["Groupe"]);
						if (is_array($G["Condition"]))foreach ($G["Condition"] as $Kc=>$C){
						if (!strstr($C,mysqlFunctions::getPrefixe($Tab,$i)."."))$Cout[] = $C;
						}
						$Gout = $G;
						$Gout["Condition"] = $Cout;
						$Gout["Condition"]["Groupe"] = $SaveGrp;
						$Out["Groupe"][$Kg] = $Gout;
						}*/

					//$Data = $Out;
				}
				$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"];
				$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = mysqlFunctions::getPrefixe($Tab,$i);
				/*				if ($i==0){
					//Si c est le premier , il faut ajouter la table de tri
					$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"];
					$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = mysqlFunctions::getPrefixe($Tab,$i)."t";
					}*/
				//Mise en place des intervalles
				if($i<sizeof($Tab)-1){
					$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"]."-Interval";
					$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = mysqlFunctions::getPrefixe($Tab,$i)."j";
				}
				$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"]."-Interval";
				$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = mysqlFunctions::getPrefixe($Tab,$i)."i";
				$Groupe["Lien"] = "AND";
				if ($Tab[$i-1]["Card"]=="0,n"||$Tab[$i-1]["Card"]=="1,n"){
					$Condition[]=mysqlFunctions::getPrefixe($Tab,$i)."i.Id=".mysqlFunctions::getPrefixe($Tab,($i-1))."t.".$Tab[$i-1]["NomEnfant"];
				}else{
					if ($i==0) $Condition[]=mysqlFunctions::getPrefixe($Tab,$i)."i.Id=0";
					else $Condition[]=mysqlFunctions::getPrefixe($Tab,$i)."i.Id=".mysqlFunctions::getPrefixe($Tab,($i-1)).".Id";
				}
				$Condition[]=mysqlFunctions::getPrefixe($Tab,$i).'j.Id='.mysqlFunctions::getPrefixe($Tab,$i).".Id";
				$Condition[]=mysqlFunctions::getPrefixe($Tab,$i).'i.bd>='.mysqlFunctions::getPrefixe($Tab,$i)."j.bd";
				$Prefs = mysqlFunctions::getPrefixe($Tab,$i);
				$Temp=$Prefs."i.bg";
				$Temp.='<=';
				$Temp.=$Prefs."j.bg";
				$Condition[] = $Temp;
				//$GLOBALS["Systeme"]->Log->log($Temp);
				$Groupe["Condition"]=$Condition;
				$Data["Groupe"][] = $Groupe;
				if (is_array($Data['GroupBy']))foreach ($Data['GroupBy'] as $g)if ($g=="m.Id")$flag=true;
				if (!$flag)$Data['GroupBy'][] = "m.Id";
				break;
			case "2":
				foreach ($this->childOf as $Child) $C = $Child;
				$Data['Table'][0]['Nom'] = $C["Titre"];
				$Data['Table'][0]['Alias'] = "m";
				$Data['Table'][1]['Nom'] = $C["Table"];
				$Data['Table'][1]['Alias'] = "j";
				$i=0;
				$Groupe["Lien"] = "AND";
				$Condition[]="m.Id=j.".$C["Titre"];
				//On ajoute une premiere table d index correspondant
				$Groupe["Condition"]=$Condition;
				$Data["Groupe"][] = $Groupe;
				$Data['Select'][] = Array ("Nom"=>"j.".$C["Titre"]."Id","Alias"=>"ClefReflexive");
				break;
		}
		if (($Tab[$i]["Card"] == "0,1" || $Tab[$i]["Card"] == "1,1")){
			$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"];
			$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = mysqlFunctions::getPrefixe($Tab,$i);
			//-------------------CONDITIONS DE JOINTURE
			$NumGroupe = sizeof($Data["Groupe"]);
			$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
			$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i).".".$Tab[$i]["Target"]."=".mysqlFunctions::getPrefixe($Tab,$i+1).".".$Tab[$i]["Champ"];
		}elseif (($Tab[$i]["Card"] == "0,n" || $Tab[$i]["Card"] == "1,n")){
			//On joint la table de liaison
			$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Table"];
			$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".$i."s";
/*			$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"];
			$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".($i+1)."s";;*/
			$NumGroupe = sizeof($Data["Groupe"]);
			//---------------CONDITIONS DE JOINTURE
			$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
			$Data['Groupe'][$NumGroupe]['Condition'][] = "j".$i.".Id=j$i"."s.".$Tab[$i]["Nom"]."Id";
			$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i+1).".".$Tab[$i]["Target"]."=j$i"."s.".$Tab[$i]["NomEnfant"];
		}
		return $Data;
	}

	function joinStandard($Tab,$Data,$i){
		//On ajoute la table de l objet concernï¿œ
		$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"];
		//Si ce n est pas le premier element alors on fait la jointure avec la paire precedente.
		if (!$Tab[$i]["NomEnfant"]){
			//Si pas de jointure
			if ($Tab[$i]["Out"])$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "m";
			else $Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j$i";
			//Gestion de la reflexivitï¿œ
			if ($Tab[$i]["Reflexive"]==1&&$Tab[$i-1]["NomEnfant"]!=$Tab[$i]["Nom"]&&!$Tab[$i]["Recherche"]) {
				//Reflexivite faible
				$NumGroupe = sizeof($Data["Groupe"]);
				$Data['Groupe'][$NumGroupe]['Lien'] = "OR";
				$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i).".".$this->findReflexive()." IS NULL";
				$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i).".".$this->findReflexive()."=''";
				$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i).".".$this->findReflexive()."=0";
			}
		}else{
			//Si jointure
			$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j$i";
			//On selectionne l'id de la requete pour l'historique
			$Data['Select'][] = Array ("Nom"=>"j$i.Id","Alias"=>"__Liaison_J$i");
			$Data['Select'][] = Array ("Valeur"=>$Tab[$i]["Nom"],"Alias"=>"__Liaison_titre_J$i");
			if (($Tab[$i]["Card"] == "0,1" || $Tab[$i]["Card"] == "1,1")){
				//-------------------CONDITIONS DE JOINTURE
				$NumGroupe = sizeof($Data["Groupe"]);
				$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
				$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i).".".$Tab[$i]["Target"]."=".mysqlFunctions::getPrefixe($Tab,$i+1).".".$Tab[$i]["Champ"];
			}else{
				//On joint la table de liaison
				$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Table"];
				$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".$i."t";
				$NumGroupe = sizeof($Data["Groupe"]);
				//---------------CONDITIONS DE JOINTURE
				$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
				$Data['Groupe'][$NumGroupe]['Condition'][] = "j$i.Id=j$i"."t.".$Tab[$i]["Nom"]."Id";
				$Data['Groupe'][$NumGroupe]['Condition'][] = mysqlFunctions::getPrefixe($Tab,$i+1).".".$Tab[$i]["Target"]."=j$i"."t.".$Tab[$i]["NomEnfant"];
			}
		}
		return $Data;
	}

	function joinParentRecursiv($Tab,$Data,$i){
		//Objet Enfant portant les filtres
		$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i+2]["Nom"];
		$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".($i+2)."p";
		//Objet ciblé
		$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"];
		$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "m";
		switch ($Tab[$i+1]["Card"]) {
			case "0,n":
			case "1,n":
				//Table de liaison entre l objet enfant et l objet parent
				$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i+1]["Table"];
				$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".($i+1)."t";
				//Liaison entre intervalle de comparaison et la table de liaison
				$Data['Groupe'][$NumGroupe]['Condition'][] = "j".$i."i.Id=j".($i+1)."t.".$Tab[$i+1]["Parent"]."Id";
				$Data['Groupe'][$NumGroupe]['Condition'][] = "j".($i+2)."p.Id=j".($i+1)."t.".$Tab[$i+1]["Champ"];
				break;
			case "0,1":
			case "1,1":
				//Liaison entre intervalle de comparaison et la table de liaison
				$Data['Groupe'][$NumGroupe]['Condition'][] = "j".$i."i.Id=j".($i+2)."p.".$Tab[$i+1]["Parent"]."Id";
				break;
		}
		switch ($Tab[$i]["Card"]) {
			case "0,1":
			case "1,1":
				//Table d intervalle  l objet parent
				$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Nom"]."-Interval";
				$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".$i."i";
				//Mise en place du filtre
				$NumGroupe = sizeof($Data["Groupe"]);
				$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
				$Data['Groupe'][$NumGroupe]['Condition'][] = "j".($i+2)."p.Id = ".$Tab[$i+2]["Recherche"];
				//Liaison entre intervalle et objet ciblé
				$Data['Groupe'][$NumGroupe]['Condition'][] = "m.Id=mj.Id";
				//Conditions intervallaires
				$Groupe["Lien"] = "AND";
				$Condition[]=mysqlFunctions::getPrefixe($Tab,$i)."i.bd<=mj.bd";
				$Condition[]=mysqlFunctions::getPrefixe($Tab,$i)."i.bg>=mj.bg";
				$Groupe["Condition"]=$Condition;
				$Data["Groupe"][] = $Groupe;
				if (is_array($Data['GroupBy']))foreach ($Data['GroupBy'] as $g)if ($g=="m.Id")$flag=true;
				if (!$flag)$Data['GroupBy'][] = "m.Id";
				break;
		}
		return $Data;
	}
	function joinParent($Tab,$Data,$i){
		//On ajoute la table de l objet concernï¿œ
		//O ajoute la table de filtre
		$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i+1]["Nom"];
		$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".($i+1)."p";
		//Table resultat
		$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Parent"];
		$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "m";
		if (($Tab[$i]["Card"] == "0,1" || $Tab[$i]["Card"] == "1,1")){
			//-------------------CONDITIONS DE RECHERCHE
			$Temp = mysqlFunctions::whereSql($Tab[$i+1],$Data,"j".($i+1)."p");
			if (is_array($Temp['Groupe']))foreach ($Temp['Groupe'] as $G){
				$Data['Groupe'][] = $G;
			}
			$Data['Suffixe'] = $Temp['Suffixe'];
			$NumGroupe = sizeof($Data["Groupe"]);
			$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
			$Data['Groupe'][$NumGroupe]['Condition'][] = "j".($i+1)."p.".$Tab[$i]["Champ"]."=m.".$Tab[$i]["Target"];
			//-------------------CONDITIONS DE JOINTURE
			$NumGroupe = sizeof($Data["Groupe"]);
			//$Data['Groupe'][$NumGroupe]['Condition'][] = $Temp['Groupe'][0]['Condition'][0];
		}else{
			//On joint la table de liaison
			$Data["Table"][sizeof($Data["Table"])]['Nom'] = $Tab[$i]["Table"];
			$Data["Table"][sizeof($Data["Table"])-1]['Alias'] = "j".$i."t";
			$Temp = mysqlFunctions::whereSql($Tab[$i+1],Array(),"j".($i+1)."p");
			if (is_array($Temp['Groupe']))foreach ($Temp['Groupe'] as $G){
				$Data['Groupe'][] = $G;
			}
			$Data['Suffixe'] = $Temp['Suffixe'];
			$NumGroupe = sizeof($Data["Groupe"]);
			$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
			//---------------CONDITIONS DE JOINTURE
			$Data['Groupe'][$NumGroupe]['Lien'] = "AND";
			$Data['Groupe'][$NumGroupe]['Condition'][] = "j".($i+1)."p.Id=j$i"."t.".$Tab[$i]["NomEnfant"];
			$Data['Groupe'][$NumGroupe]['Condition'][] = "m.".$Tab[$i]["Target"]."=j$i"."t.".$Tab[$i]["Parent"]."Id";
			if (is_array($Data['GroupBy']))foreach ($Data['GroupBy'] as $g)if ($g=="m.Id")$flag=true;
			if (!$flag)$Data['GroupBy'][] = "m.Id";
		}
		if (is_array($Tab[$i+2])){
			//Ajout d un filtre sur la sortie
			$Temp = mysqlFunctions::whereSql($Tab[$i+2],$Data,"m");
			$Data['Groupe'][$NumGroupe]['Condition'][] = $Temp['Groupe'][1]['Condition'][0];
			$Data['Suffixe'] = $Temp['Suffixe'];
		}
		return $Data;
	}

	//Definit les prefixe de table en fonction de l emplacement dans le tableau d analyse
	function getPrefixe($Tab,$i){
		return ($i==sizeof($Tab)-1||$Tab[$i]["Parent"])?"m":"j".$i;
	}
	//Definit les prefixe de table en fonction de l emplacement dans le tableau d analyse
	function getTableAssoc($P,$C){
		return ($i==sizeof($Tab)-1)?"m":"j".$i;
	}

	//Cree les conditions de jointures necessaires dans une requete
	function joinSql($Tab,$Data){
		//On boucle sur les objets precedents
		$var  = (sizeof($Tab)>MAIN_DB_RECURSIV_LIMIT&&MAIN_DB_RECURSIV_LIMIT)?sizeof($Tab)-1-MAIN_DB_RECURSIV_LIMIT:0;
		for ($i=$var;$i<sizeof($Tab);$i++){
			if ($Tab[$i+1]["Parent"]==$Tab[$i]["Nom"]&&$Tab[$i]["Recherche"]=="*") {
				$Data = mysqlFunctions::joinParentRecursiv($Tab,$Data,$i);
				$Data["Special"] = "RECURSIV";
				$i++;
				$i++;
			}elseif ($Tab[$i]["Parent"]) {
				$Data = mysqlFunctions::joinParent($Tab,$Data,$i);
				$i = sizeof($Tab)-1;
			}elseif ($Tab[$i]["Recherche"]=="*") {
				//RECURSIVE
				$Data = mysqlFunctions::joinRecursiv($Tab,$Data,$i);
				$Data["Special"] = "RECURSIV";
			}else{
				//CHAINE
				$Data = mysqlFunctions::joinStandard($Tab,$Data,$i);
				$Data = mysqlFunctions::whereSql($Tab[$i],$Data,mysqlFunctions::getPrefixe($Tab,$i));
			}
		}
		return $Data;
	}



	function multiConditions($c,$Tab,$prefixe)
	{
		preg_match("#(.*)([=!+<>~]{2})(.*)#",$c,$Out);
		if (sizeof($Out)<2)preg_match("#(.*)([=!+<>~]{1})(.*)#",$c,$Out);
		$T = explode(".",$Out[1]);
		if (sizeof($T)>1)
		  {$Pref=$T[0].".";$Out[1] = $T[1];}
		else $Pref=$prefixe.".";
		switch ($Out[2]){
			case "=":
			case ">":
			case "<":
			case "<=":
			case ">=":
			case "!=":
				if (is_numeric($Out[3])||$Out[3]=="NULL") $Data['Condition'][] = "$Pref".$Out[1]."".$Out[2]."".$Out[3]."";
				else $Data['Condition'][] = "$Pref`".$this->langProp($Out[1])."`".$Out[2]."'".$Out[3]."'";
				$Made=1;
				$Data["Lien"] = "AND";
				break;
		        case "><":
            			$Fourchette = explode("-->",$Out[3]);
				$Data['Condition'][] = "$Pref`".$Out[1]."`>=".$Fourchette[0];
				$Data['Condition'][] = "$Pref`".$Out[1]."`<=".$Fourchette[1];
				$Made=1;
				$Data['Lien']="AND";
				break;
		        case "!!":
				$Data['Condition'][] = "$Pref`".$Out[1]."` IS NULL";
				$Made=1;
				$Data["Lien"] = "AND";
		                break;
			case "~":
				$Data['Lien'] = "OR";
				//Suppression des pluriels
				//$c = preg_replace("#(.*)(s|e)$#","$1",$Out[3]);
				$mc= $Out[3];
				if ($Out[1]!=""){
					$Rt = explode(" ",$mc);
					if (sizeof($Rt)>1){
						//Si il y a plusierus mots clefs alors on fait une recherche avec select imbrique et exacte.
						//Recherche d'espaces
						foreach ($Rt as $t) {if ($g)$likein.=",";else $g=true;$likein .= "'$t'";}
						$Data['Condition'][] = "$Pref".$Out[1]." IN ($likein)";
						$Data['Suffixe'][] = "having count(*) >= ".sizeof($Rt);
					}else{
						//si il y a qu'u mot clef alors on fait une recherche floue
						$Data['Condition'][] = "$Pref".$Out[1]." LIKE '".$mc."%'";
					}
				}else{
					$Type="string";
					$IdObjClass =$GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($Tab["Nom"]);
					$Obj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$IdObjClass];
					foreach ($Obj->Cibles as $Nom=>$sOrder){
						if ($Obj->getPropType($Nom)==$Type) {
							//Gestion des langues
							$PropName = $this->langProp($Nom,$Type);
							$Data['Condition'][] ="$Pref".$PropName." LIKE \"%".$mc."%\"";
						}
					}
				}
				$Made=1;
				break;
			default:
				$Made=0;
				break;
		}
		if (is_numeric($c)&&!$Made) {
			//IntSearch
			$Data['Condition'][] = "$prefixe.Id=".$c."";
		}elseif (!$Made){
			//StringSearch
			$Type="string";
			$Data['Lien'] = "AND";
			$IdObjClass = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($Tab["Nom"]);
			$Obj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$IdObjClass];
			$imbriqSql="$prefixe.Id= (SELECT Id FROM `".$this->Prefix.$Obj->titre."` WHERE ";
			foreach ($Obj->Cibles as $Nom=>$sOrder){
				if ($Obj->getPropType($Nom)==$Type) {
					//Gestion des langues
					$PropName = $this->langProp($Nom,$Type);
					if ($f) $imbriqSql.="OR";else $f=true;
					$imbriqSql.= "(`".$PropName."` = \"$c\")";
					if (AUTO_COMPLETE_LANG&&!$GLOBALS["Systeme"]->User->Admin&&$Obj->Proprietes[$Nom]["special"]=="multi"){
						foreach ($GLOBALS["Systeme"]->Conf->get("GENERAL::LANGUAGE") as $Key=>$Lang) {
							if ($GLOBALS["Systeme"]->DefaultLanguage!=$Lang["TITLE"]){
								if ($f) $imbriqSql.="OR";else $f=true;
								if ($Lang["DEFAULT"]!=1){
									$imbriqSql.= "(`".$Key."-".$Nom."` = \"$c\")";
								}else $imbriqSql.= "(`".$Nom."` = \"$c\")";
							}
						}
					}
				}
			}
			$imbriqSql.="LIMIT 0,1)";
			//echo "--> REQUETE IMBRIQUEE => ".$imbriqSql."\r\n";
			$Data['Condition'][] =$imbriqSql;
			/*$Type="string";
			 $Data['Lien'] = "OR";
			 $IdObjClass = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($Tab["Nom"]);
			 $Obj = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$IdObjClass];
			 foreach ($Obj->Cibles as $Nom=>$sOrder){
				if ($Obj->getPropType($Nom)==$Type) {
				//Gestion des langues
				$PropName = $this->langProp($Nom,$Type);
				$Data['Condition'][] ="$prefixe.".$PropName." = \"$c\"";
				}
				}*/

		}
		return $Data;
	}

	function getMultiSearch($Tab,$Data,$Rech,$prefixe)
	{
		/*On créé un tableau en découpant chaque (!!) et en notant son parent, son départ, son arrivée, et sa profondeur */
		$TRech = $Rech;$brackets = Array();
		$nump = 0;$prof = $maxprof = 1;
		$lastWithChilds[]=0;
		$brackets[0] = Array("prof"=>0,"opened"=>0,"closed"=>strlen($Rech));
		while (strpos($TRech,'(!') !== false || strpos($TRech,'!)') !== false)
		{
			$nextOpen = strpos($TRech,'(!');
			$nextClose = strpos($TRech,'!)');
			//Si le plus proche est une ouverture
			if ($nextOpen!== false&&($nextClose>$nextOpen||$nextClose===false))
			{
				$brackets[++$nump]["opened"]=$truePos+$nextOpen+2;
				$brackets[$nump]["prof"]=$prof++;
				if ($lastDone=="o") $lastWithChilds[] = $nump-1;
				$brackets[$nump]["parent"] = $lastWithChilds[count($lastWithChilds)-1];
				$brackets[$nump]["lwc"] = $lastWithChilds;
				$TRech = substr($TRech,$nextOpen+2);
				$truePos = $truePos+$nextOpen+2;
				$lastDone = "o";
				if ($maxprof<$prof) $maxprof = $prof;
			}
			//Si le plus proche est une fermeture
			if ($nextClose!== false&&($nextOpen>$nextClose||$nextOpen===false))
			{
				$Index = 0;
				foreach(array_reverse($brackets,true) as $I=>$V)
				{
					if ($Index==0&&empty($V["closed"])) $Index = $I;
				}
				$brackets[$Index]["closed"]=$truePos+$nextClose;
				$TRech = substr($TRech,$nextClose+2);
				$truePos = $truePos+$nextClose+2;
				$prof--;
				if ($lastDone=="c")
				{
					unset($lastWithChilds[count($lastWithChilds)-1]);
				}
				$lastDone = "c";
			}
		}
		/*On range le tableau pour le rendre un peu recursif*/
		for ($j=$maxprof;$j>=0;$j--)
		{
			foreach ($brackets as $K=>&$brak)
			{
				if ($brak["prof"]==$j)
				{
					$FullCondition = substr($Rech,$brak["opened"],$brak["closed"]-$brak["opened"]);
					$FullCondition = preg_replace("#(\(\!.*\!\))#","",$FullCondition);
					$brak["Lien"] = (strpos($FullCondition,"+")) ? "OR":"AND";
					$Conditions = ($brak["Lien"]=="OR") ? explode("+",$FullCondition):explode("&",$FullCondition);
					foreach ($Conditions as $C)
					{
						if (!empty($C)){
							$tempi = mysqlFunctions::multiConditions($C,$Tab,$prefixe);
							if (is_array($tempi["Suffixe"])) $Data["Suffixe"] = $tempi["Suffixe"];
							$brak["Condition"]["Groupe"][] =  $tempi;
						}
					}
					unset($brak["opened"]);
					unset($brak["closed"]);
					unset($brak["lwc"]);
					unset($brak["prof"]);
					if ($j>0)
					{
						$par = $brak["parent"];
						unset($brak["parent"]);
						$brackets[$par]["Condition"]["Groupe"][] = $brackets[$K];
						unset($brackets[$K]);
					}
				}
			}
		}
		$Data["Groupe"][count($Data["Groupe"])] = $brackets[0];
		return $Data;
	}

	function whereSql($Tab,$Data,$prefixe) {

		if (!empty($Tab["Recherche"])) $Data = mysqlFunctions::getMultiSearch($Tab,$Data,$Tab["Recherche"],$prefixe);
		// 		if ($this->titre=="Produit")print_r($Data);
		return $Data;
	}

	/*Fonction récursive:
	 * Créé une requete a partir d'un groupe de conditions
	 * Condition d'arret : Tab[Condition][Groupe].length = 0
	 * Parametre : Tab::tableau
	 * Retourne : ::String
	 */
	function writeConditions($Tab){
		$Grps = $Tab["Condition"]["Groupe"];
		unset($Tab["Condition"]["Groupe"]);
		if (empty($Tab["Lien"])) $Tab["Lien"]="AND";
		$sqlCond = "(";
		$queryStarted=false;
		for ($i=0;$i<count($Tab["Condition"]);$i++){
			if ($i>0) $sqlCond.= " ".$Tab["Lien"]." ";
			$sqlCond.= "(".$Tab["Condition"][$i].")";
			$queryStarted=true;
		}
		for ($i=0;$i<count($Grps);$i++){
			if ($i>0||$queryStarted) $sqlCond.= " ".$Tab["Lien"]." ";
			$sqlCond.= mysqlFunctions::writeConditions($Grps[$i]);
		}
		$sqlCond .= ")";
		return $sqlCond;
	}

	//Constructeur magique de recherche en fonction du tableau d analyse
	function createSql($Type,$Data,$Select=""){
		//Ajout des parametres principaux
		if (!$Select) {
			$sql='SELECT m.Id,m.userCreate,m.tmsCreate,m.tmsEdit,m.userEdit,m.uid,m.gid,m.umod,m.gmod,m.omod';
			foreach ($this->Proprietes as $Key=>$Prop){
				//Priorites de langage
				if (array_key_exists($Key,$this->Proprietes)) $Special = $this->Proprietes[$Key]["special"];
				if (!empty($Prop["Ref"])) $sql.=",r".$Prop["Ref_Level"].".$Key";
				elseif ($Special=="multi"&&$GLOBALS["Systeme"]->User->Admin){
					$sql.=",m.`".$this->langProp($Key)."` as `".$Key."`";
					foreach ($GLOBALS["Systeme"]->Conf->get("GENERAL::LANGUAGE") as $Cod=>$Lang) {
						if (!$Lang["DEFAULT"]) $sql.=",m.`".$Cod."-".$Key."`";
					}
				}elseif ($Special=="multi"&&AUTO_COMPLETE_LANG&&$GLOBALS["Systeme"]->LangageDefaut!=$GLOBALS["Systeme"]->DefaultLanguage){
					$sql.=",m.`".$this->langProp($Key)."` as `".$Key."`";
					foreach ($GLOBALS["Systeme"]->Conf->get("GENERAL::LANGUAGE") as $Cod=>$Lang) {
						if ($Lang["DEFAULT"]) $sql.=",m.`".$Key."`as `$Cod-".$Key."`";
					}
				}else $sql.=",m.`".$this->langProp($Key)."` as `".$Key."`";
			}
			
			//Ajout des champs Select optionnels
			if(is_array($Data['Select'])) {
				foreach ($Data['Select'] as $Selection){
					if (!empty($Selection['Nom'])){
						$sql.=",".$Selection['Nom']." as `".$Selection['Alias'].'`';
					}else{
						$sql.=",'".$Selection['Valeur']."' as `".$Selection['Alias'].'`';
					}
				}
			}

			if ($this->isReflexive()==1){
				$sql.=",m.".$this->findReflexive()." as `ClefReflexive`";

			}
			if ($this->isReflexive()&&$Type!="SELECT_INTERVAL"){ //&&$Data["Special"]=="RECURSIV"){
				$sql.=",mj.Bd as `Bd`,mj.Bg as `Bg`";
				$Table["Nom"] = $this->titre."-Interval";
				$Table["Alias"] = "mj";
				$Data["Table"][] = $Table;
				$Data['Groupe'][]['Condition'][] ="mj.Id = m.Id";
			}
		}else $sql = 'SELECT '.$Select;
		//Ajout des tables et de leur alias
		$sql.=" FROM ";
		foreach ($Data['Table'] as $Table) {
			if ($Flag) $sql.=",";$Flag=true;
			$Prefix= ($Table['Option']=="NO_PREFIX") ? "":$this->Prefix;
			$sql.="`".$Prefix.$Table['Nom'].'` as `'.$Table['Alias'].'`';
			//Gestion des Joins
			if (is_array($Table['Join'])) foreach ($Table['Join'] as $Jo){
				$Prefix= ($Jo['Option']=="NO_PREFIX") ? "":$this->Prefix;
				$sql.=" ".$Jo['Side']." JOIN `".$Prefix.$Jo['Table'].'` as `'.$Jo['Alias'].'` ON ('.$Jo['On'].')';
			}
		}
		$r=0;
		$sql.= ' WHERE 1';
		//Gestion des droits
		if (!empty($GLOBALS["Systeme"]->User->Id) && !$GLOBALS["Systeme"]->User->Admin && $this->titre!="Connexion"){
			$GroupeDroits = Array("Lien"=>"OR");
			$GroupeDroits["Condition"][] = "m.omod>=3";
			$GGroupeDroits = Array ("Lien"=>"AND");
			$GGroupeDroits["Condition"][] = "m.umod>=3";
			$GGroupeDroits["Condition"][] = "m.uid=".$GLOBALS["Systeme"]->User->Id;
			$GroupeDroits["Condition"]["Groupe"][] = $GGroupeDroits;
			if (is_array($GLOBALS["Systeme"]->User->Groups)) foreach ($GLOBALS["Systeme"]->User->Groups as $Grp){
				$GGroupeDroits = Array ("Lien"=>"AND");
				$GGroupeDroits["Condition"][] = "m.gmod>=3";
				$GGroupeDroits["Condition"][] = "m.gid=".$Grp->Id;
				$GroupeDroits["Condition"]["Groupe"][] = $GGroupeDroits;
			}
			$Data["Groupe"][] = $GroupeDroits;
		}
		//Ajout des conditions et des groupes de conditions
		$Linking = " AND ";
		if (is_array($Data['Groupe'])){
			foreach ($Data['Groupe'] as $Grp){
				$Flag_2 = false;
				$NString = mysqlFunctions::writeConditions($Grp);
				if ($NString!=""&&$NString!="()") $sql.=$Linking." (".$NString.") ";
			}
		}
		//Gestion des GROUP BY
		if (is_array($Data['GroupBy'])&&($Select==""||is_array($Data['Suffixe']))){
			$sql.=" GROUP BY ";
			foreach ($Data['GroupBy'] as $Group){
				
				$sql.= "$Flag2 $Group";
				$Flag_2 = ",";
			}
		}
		if (is_array($Data['Suffixe'])){
			foreach ($Data['Suffixe'] as $Group){
				$sql.= "$Flag2 $Group ";
			}
		}
		//echo $sql;
		return $sql;
	}

	//----------------------------------------------//
	// INTERROGATION				//
	//----------------------------------------------//
	//REnvoie le nom de la table de l objectClass en cours
	function getTableName($i=0){
		return $this->Prefix.$this->titre;;
	}

	//Renvoie le proprietaire de l objet en cours
	function idPossess($id){
		if(!count($this->ObjectTable)){
			$sql = "select * from `".$this->Prefix.$this->titre."` ";
			$sql .= "where (gId=$gId) OR (omod>1)";
			$requete = mysql_query($sql);
			while ($Resultat = mysql_fetch_assoc($requete)){
				$this->ObjectTable[] = $Resultat;
			}
		}
		foreach ($this->ObjectTable as $Objet){
			if ($id==$Objet["Id"]) return true;
		}
		return false;
	}

	function countDb() {
		$sql="SELECT COUNT(*) AS Size FROM `".$this->Prefix.$this->titre."`";
		$Result=$this->executeSql($sql,"SELECT_SYS");
		return $Result["Size"];
	}

}
